package com.jingge.autojob.skeleton.model.builder;

import com.jingge.autojob.skeleton.framework.task.AutoJobTrigger;
import com.jingge.autojob.skeleton.model.task.remote.RemoteTask;
import okhttp3.HttpUrl;

import java.util.concurrent.TimeUnit;

/**
 * @author JingGe(* ^ ▽ ^ *)
 * @date 2023-09-12 17:24
 * @email 1158055613@qq.com
 */
public class RemoteJobConfig {
    private AutoJobTrigger trigger;
    private boolean isChildTask;
    private final String host;
    private final int port;
    private final String uri;
    private Object header;
    private Object body;
    private Object queryParams;
    private long connectTimeout = 10000;
    private long readTimeout = 30000;
    private long writeTimeout = 30000;

    private RemoteJobConfig(String host, int port, String uri) {
        this.host = host;
        this.port = port;
        this.uri = uri;
    }

    public static Builder builder(String url) {
        return new Builder(url);
    }

    public static Builder builder(String host, int port, String uri) {
        return new Builder(host, port, uri);
    }

    public static Builder builder(String host, int port) {
        return new Builder(host, port);
    }

    public AutoJobTrigger getTrigger() {
        return trigger;
    }

    public boolean isChildTask() {
        return isChildTask;
    }

    public String getHost() {
        return host;
    }

    public int getPort() {
        return port;
    }

    public String getUri() {
        return uri;
    }

    public Object getHeader() {
        return header;
    }

    public Object getBody() {
        return body;
    }

    public Object getQueryParams() {
        return queryParams;
    }

    public long getConnectTimeout() {
        return connectTimeout;
    }

    public long getReadTimeout() {
        return readTimeout;
    }

    public long getWriteTimeout() {
        return writeTimeout;
    }

    public static class Builder {
        private AutoJobTrigger trigger;
        private boolean isChildTask;
        private final String host;
        private final int port;
        private String uri;
        private Object header;
        private Object body;
        private Object queryParams;
        private long connectTimeout = 10000;
        private long readTimeout = 30000;
        private long writeTimeout = 30000;

        public Builder(String url) {
            HttpUrl uri = HttpUrl.parse(url);
            if (uri == null) {
                throw new IllegalArgumentException("不合法的URL");
            }
            this.uri = uri
                    .uri()
                    .getPath();
            host = uri.host();
            port = uri.port();
        }

        public Builder(String host, int port, String uri) {
            this.host = host;
            this.port = port;
            this.uri = uri;
        }

        public Builder(String host, int port) {
            this.host = host;
            this.port = port;
        }

        /**
         * 添加一个简单触发器，添加多个触发器时前者将被后者覆盖
         *
         * @param firstTriggeringTime 首次触发时间
         * @param repeatTimes         重复次数，任务总触发次数=1+repeatTimes，-1表示无限次触发
         * @param cycle               周期
         * @param unit                时间单位
         * @return com.example.autojob.skeleton.model.builder.AutoJobScriptTaskBuilder
         * @author Huang Yongxiang
         * @date 2022/10/27 9:59
         */
        public Builder addASimpleTrigger(long firstTriggeringTime, int repeatTimes, long cycle, TimeUnit unit) {
            this.trigger = AutoJobTriggerFactory.newSimpleTrigger(firstTriggeringTime, repeatTimes, cycle, unit);
            return this;
        }

        /**
         * 添加一个cron-like表达式的触发器，添加多个触发器时前者将被后者覆盖
         *
         * @param cronExpression cron-like表达式
         * @param repeatTimes    重复次数，任务总触发次数=1+repeatTimes，-1表示无限次触发
         * @return com.example.autojob.skeleton.model.builder.AutoJobScriptTaskBuilder
         * @author Huang Yongxiang
         * @date 2022/10/27 10:03
         */
        public Builder addACronExpressionTrigger(String cronExpression, int repeatTimes) {
            this.trigger = AutoJobTriggerFactory.newCronExpressionTrigger(cronExpression, repeatTimes);
            return this;
        }

        /**
         * 添加一个子任务触发器，该任务将会作为一个子任务参与调度，添加多个触发器时前者将被后者覆盖
         *
         * @return com.example.autojob.skeleton.model.builder.AutoJobScriptTaskBuilder
         * @author Huang Yongxiang
         * @date 2022/10/27 10:09
         */
        public Builder addAChildTaskTrigger() {
            this.trigger = AutoJobTriggerFactory.newChildTrigger();
            isChildTask = true;
            return this;
        }

        /**
         * 添加一个延迟触发器，任务将会在给定延迟后触发一次，添加多个触发器时前者将被后者覆盖
         *
         * @param delay 距离现在延迟执行的时间
         * @param unit  时间单位
         * @return com.example.autojob.skeleton.model.builder.AutoJobScriptTaskBuilder
         * @author Huang Yongxiang
         * @date 2022/10/27 10:12
         */
        public Builder addADelayTrigger(long delay, TimeUnit unit) {
            this.trigger = AutoJobTriggerFactory.newDelayTrigger(delay, unit);
            return this;
        }


        public Builder setHeader(Object header) {
            this.header = header;
            return this;
        }

        public Builder setBody(Object body) {
            this.body = body;
            return this;
        }

        public Builder setQueryParams(Object queryParams) {
            this.queryParams = queryParams;
            return this;
        }

        public Builder setConnectTimeout(long connectTimeout, TimeUnit unit) {
            this.connectTimeout = unit.toMillis(connectTimeout);
            return this;
        }

        public Builder setReadTimeout(long readTimeout, TimeUnit unit) {
            this.readTimeout = unit.toMillis(readTimeout);
            return this;
        }

        public Builder setWriteTimeout(long writeTimeout, TimeUnit unit) {
            this.writeTimeout = unit.toMillis(writeTimeout);
            return this;
        }

        public RemoteJobConfig build() {
            RemoteJobConfig config = new RemoteJobConfig(host, port, uri);
            config.header = header;
            config.body = body;
            config.trigger = trigger;
            config.isChildTask = isChildTask;
            config.queryParams = queryParams;
            config.connectTimeout = connectTimeout;
            config.readTimeout = readTimeout;
            config.writeTimeout = writeTimeout;
            return config;
        }
    }

}
